Skip to content

Conversation

@potrue
Copy link
Owner

@potrue potrue commented Aug 5, 2025

return std::max(rob_line(span_without_last), rob_line(span_without_first));
}
private:
int rob_line(std::span<int>& nums) {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

std::span は軽量な軽量なデータ参照のため、値渡ししてしまってよいと思います。

#include <iostream>
#include <span>

int main()
{
    std::span<int> s;
    std::cout << sizeof(s) << std::endl;
}
16

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sizeofでサイズをチェックする方法も参考になります。ありがとうございます。

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

補足すると、 Linux で使用される System V AMD64 ABI では 16 バイトまでのデータはレジスター渡しになるようです。

https://azelpg.gitlab.io/azsky2/note/prog/asm64/22_systemv.html

構造体全体を、2つの 8 byte 値で扱うことが出来る場合、(使用可能なレジスタがあれば) レジスタに格納されます。
2つの 8 byte 値で扱えない場合は、構造体全体がスタックに格納されます。

https://learn.microsoft.com/ja-jp/cpp/build/x64-calling-convention?view=msvc-170&utm_source=chatgpt.com

16 バイトの引数は参照渡しされます。

パフォーマンスが重要な場合については、コンパイラーから出力されるアセンブラを確認したり、マイクロベンチマークを取るのが良いと思います。そうでない場合は、ひとまず値渡しで良いと思います。

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

なるほど、ありがとうございます!参考になります。

if (nums.size() == 1) {
return nums[0];
}
auto rob_linearly = [&nums](int begin, int end) -> int {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ラムダ式は、長くなると、ソースコードを読むにあたり、目線をラムダ関数の前後で大きく動かさなければならなくなる場合があります。このため、読み手を疲れさせる場合があります。個人的には private なクラス関数としたほうが良いと思います。

ただ、イベントハンドラーを大量に書かなければならない場合や、並列計算フレームワークで計算ロジックをネストさせたい場合、キャプチャーを使いたい場合など、場合に応じて使い分けるのが良いと思います。

@potrue potrue mentioned this pull request Aug 5, 2025
書いているときは気づきませんでしたが空の配列が渡された時に`nums.begin() + 1`とか`nums.end() - 1`でバグりそうなので`nums.size() == 0`の時の場合分けが欲しいかもしれませんね。

```cpp
class Solution {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM です。個人的にはこれが一番好きですね。

}
return current_max;
}
};

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

std::span は初めて知りました。直接イテレータを渡しても書けそうな気がしたのですが、std::span を介することで vector のように扱えて直感的ということでしょうか?

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

おっしゃる通りイテレーターを二つ渡しても書けると思います。利点もその通りだと思います。
イテレーターで渡した場合は

for (const int num : nums) {
...
}

for (it = begin; it < end; ++it) {
    int num = *it
    ...
}

のような形になりますね。
恐らく一つ前の問題(198. House Robber)で入力がvectorとして与えられていたので、その問題で書いたコードを再利用したいという思惑が無意識的に働きstd::spanを選択したんだと思います笑

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

わかりました。ありがとうございます!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants